package util

import (
	"golang.org/x/text/encoding/simplifiedchinese"
	"golang.org/x/text/transform"
	"io/ioutil"
	"os"
	"reflect"
	"strconv"
	"strings"
	"time"
)

func UTF82GBK(src string) (string, error) {
	reader := transform.NewReader(strings.NewReader(src), simplifiedchinese.GBK.NewEncoder())
	if buf, err := ioutil.ReadAll(reader); err != nil {
		return "", err
	} else {
		return string(buf), nil
	}
}

func ExportCsv(filePath string, exportObj *[]interface{}, includeField *[]string) error {

	fp, err := os.Create(filePath) // 创建文件句柄
	if err != nil {
		return err
	}
	defer fp.Close()

	//第一行列名
	typeOfObj := reflect.TypeOf((*exportObj)[0])
	var lineOneStr string
	for i := 0; i < typeOfObj.NumField(); i++ {
		//反射获取结构体字段名
		field := typeOfObj.Field(i)
		if checkIgnoreField(field.Name, includeField) {
			lineOneStr = lineOneStr + field.Name + ","
		}
	}
	if line, err := UTF82GBK(lineOneStr); err == nil { // 写入第一行标题
		fp.WriteString(line + "\n")
	}

	//组装后面记录中的详细数据
	detailLines := make([]string, 0)
	for _, value := range *exportObj {
		typeOf := reflect.TypeOf(value)
		valueOf := reflect.ValueOf(value)
		//反射获取每个结构体成员数据值
		var lineStr string
		for i := 0; i < typeOf.NumField(); i++ {
			field := typeOf.Field(i)
			if checkIgnoreField(field.Name, includeField) {
				switch field.Type.Kind().String() {
				case "string":
					lineStr = lineStr + valueOf.Field(i).String() + ","
				case "int64":
					lineStr = lineStr + strconv.FormatInt(valueOf.Field(i).Int(), 10) + ","
				case "int32":
					lineStr = lineStr + strconv.FormatInt(valueOf.Field(i).Int(), 10) + ","
				case "int":
					lineStr = lineStr + strconv.Itoa(int(valueOf.Field(i).Int())) + ","
				case "float64":
					lineStr = lineStr + strconv.FormatFloat(valueOf.Field(i).Float(), 'E', -1, 64) + ","
				case "float32":
					lineStr = lineStr + strconv.FormatFloat(valueOf.Field(i).Float(), 'E', -1, 32) + ","
				case "time.Time":
					i2 := valueOf.Field(i).Interface().(time.Time)
					lineStr = lineStr + i2.Format("2006-01-02 15:04:05") + ","
				default:
					lineStr = lineStr + "unknown,"
				}
			}
		}
		detailLines = append(detailLines, lineStr)
	}

	for _, valus := range detailLines {
		if line, err := UTF82GBK(valus); err == nil {
			fp.WriteString(line + "\n")
		}
	}

	return nil
}

//保留指定字段
func checkIgnoreField(field string, ignoreFields *[]string) bool {
	if ignoreFields == nil {
		return true
	}
	for _, value := range *ignoreFields {
		if field == value {
			return true
		}
	}
	return false
}
